package cn.schoolwow.quickapi.module.business.apidoc.service;

import cn.schoolwow.quickapi.domain.QuickAPIOption;
import cn.schoolwow.quickapi.module.business.api.domain.API;
import cn.schoolwow.quickapi.module.business.apiController.domain.APIController;
import cn.schoolwow.quickapi.module.business.apiParameter.domain.APIParameter;
import cn.schoolwow.quickapi.module.common.domain.APIDocument;
import cn.schoolwow.quickapi.module.common.domain.APIEntity;
import cn.schoolwow.quickapi.module.common.domain.APIField;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.flow.BusinessFlow;
import cn.schoolwow.util.domain.query.instanceList.QueryInstanceList;
import com.thoughtworks.qdox.JavaProjectBuilder;
import com.thoughtworks.qdox.model.DocletTag;
import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaField;
import com.thoughtworks.qdox.model.JavaMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.List;

public class SetAPICommentFlow implements BusinessFlow {
    private Logger logger = LoggerFactory.getLogger(SetAPICommentFlow.class);

    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        checkSourceProject(flowContext);
        setAPIControllerComment(flowContext);
        setAPIComment(flowContext);
        setAPIParameterComment(flowContext);
        setAPIEntityComment(flowContext);
    }

    @Override
    public String name() {
        return "设置API注释";
    }

    private void checkSourceProject(FlowContext flowContext){
        QuickAPIOption quickAPIOption = flowContext.checkInstanceData(QuickAPIOption.class);

        if(null==quickAPIOption.sourceJavaProjectPath||quickAPIOption.sourceJavaProjectPath.isEmpty()){
            flowContext.brokenCurrentFlow("java源文件路径不存在");
        }

        File sourceFolder = new File(quickAPIOption.sourceJavaProjectPath);
        if(!sourceFolder.exists()){
            logger.warn("java源文件路径不存在!路径:"+sourceFolder.getAbsolutePath());
            flowContext.brokenCurrentFlow("java源文件路径不存在");
        }
    }

    private void setAPIControllerComment(FlowContext flowContext){
        APIDocument apiDocument = flowContext.checkInstanceData(APIDocument.class);
        JavaProjectBuilder javaProjectBuilder = flowContext.checkInstanceData(JavaProjectBuilder.class);

        for(APIController apiController:apiDocument.apiControllerList){
            JavaClass javaClass = javaProjectBuilder.getClassByName(apiController.className);
            apiController.description = javaClass.getComment();
            apiController.javaClass = javaClass;
        }
    }

    private void setAPIComment(FlowContext flowContext){
        APIDocument apiDocument = flowContext.checkInstanceData(APIDocument.class);
        JavaProjectBuilder javaProjectBuilder = flowContext.checkInstanceData(JavaProjectBuilder.class);

        for(API api:apiDocument.apiList){
            JavaClass javaClass = javaProjectBuilder.getClassByName(api.apiController.className);
            api.javaClass = javaClass;
            List<JavaMethod> javaMethodList = javaClass.getMethods();
            for(JavaMethod javaMethod:javaMethodList){
                if(!javaMethod.getModifiers().contains("public")){
                    continue;
                }
                if(javaMethod.getName().equalsIgnoreCase(api.method.getName())){
                    api.description = javaMethod.getComment();
                    api.javaMethod = javaMethod;
                }
            }
        }
    }

    private void setAPIParameterComment(FlowContext flowContext){
        APIDocument apiDocument = flowContext.checkInstanceData(APIDocument.class);
        JavaProjectBuilder javaProjectBuilder = flowContext.checkInstanceData(JavaProjectBuilder.class);

        for(API api:apiDocument.apiList){
            JavaClass javaClass = javaProjectBuilder.getClassByName(api.apiController.className);
            List<JavaMethod> javaMethodList = javaClass.getMethods();
            for(JavaMethod javaMethod:javaMethodList){
                if(!javaMethod.getModifiers().contains("public")){
                    continue;
                }
                List<DocletTag> docletTagList = javaMethod.getTagsByName("param");
                for(DocletTag docletTag:docletTagList){
                    for(APIParameter apiParameter:api.apiParameterList){
                        if(docletTag.getValue().startsWith(apiParameter.name)){
                            apiParameter.description = docletTag.getValue();
                            apiParameter.javaClass = javaClass;
                            apiParameter.javaMethod = javaMethod;
                            api.parameterData.put(apiParameter.name, apiParameter.description);
                            break;
                        }
                    }
                }
            }
        }
    }

    private void setAPIEntityComment(FlowContext flowContext){
        JavaProjectBuilder javaProjectBuilder = flowContext.checkInstanceData(JavaProjectBuilder.class);
        APIDocument apiDocument = flowContext.checkInstanceData(APIDocument.class);

        for(APIEntity apiEntity:apiDocument.apiEntityMap.values()){
            JavaClass javaClass = javaProjectBuilder.getClassByName(apiEntity.className);
            apiEntity.javaClass = javaClass;

            List<JavaField> javaFieldList = javaClass.getFields();

            for(JavaField javaField:javaFieldList){
                APIField apiField = QueryInstanceList.newQuery(apiEntity.apiFieldList)
                        .addQuery("name", javaField.getName())
                        .execute()
                        .getOne();
                if(null!=apiField){
                    apiField.description = javaField.getComment();
                    apiField.javaField = javaField;
                }
            }
        }
    }
}
